<?php

namespace app\common\middleware;

use app\adminapi\model\sysuser\SysUserDO;
use app\adminapi\service\SysOperLogService;
use app\common\enum\BusinessStatus;
use app\common\enum\BusinessType;
use app\common\utils\AddressUtils;
use app\common\utils\IpUtils;
use think\facade\Env;

class LogMiddleware
{
    public function handle($request, \Closure $next)
    {
        $response = $next($request);
        // 获取控制器
        $controller = new \ReflectionClass($request->controllerObject);
        // 获取方法名
        $actionName = request()->action();
        // 获取当前用户
        $user = (new SysUserDO())->where('user_id', $request->adminId)->find();
        // 设置操作时间、请求地址
        $operLogParam = [
            'oper_time' => time(),
            'status' => BusinessStatus::SUCCESS,
            'oper_ip' => IpUtils::getIpAddr(),
            'oper_url' => request()->url(),
            'oper_location' => AddressUtils::getRealAddressByIP(IpUtils::getIpAddr())
        ];
        if (!empty($user)) {
            $operLogParam['oper_name'] = $user->userName;
        }
        if ($response->getCode() !== 200) {
            $operLogParam['status'] = BusinessStatus::FAIL;
            $operLogParam['error_msg'] = $response->getMessage();
        }
        // 记录请求参数
        $params = $request->param();

        //过滤密码参数
        if (isset($params['password'])) {
            $params['password'] = "******";
        }
        if (isset($params['newPassword'])) {
            $params['newPassword'] = "******";
        }
        if (isset($params['oldPassword'])) {
            $params['oldPassword'] = "******";
        }
        $operLogParam['req_param'] = json_encode($params, JSON_UNESCAPED_UNICODE);
        $operLogParam['rep_param'] = $response->getContent();
        // 设置方法名称
        $operLogParam['method'] = $controller->getName() . '\\' . $actionName . '()';
        // 设置请求方式
        $operLogParam['req_method'] = request()->method();
        // 设置消耗时间
        $operLogParam['cost_time'] = $operLogParam['oper_time'] - request()->requestStartTime;
        $this->processAnnoationParam($controller->getName(), $actionName, $operLogParam);
        // 记录操作日志
        (new SysOperLogService())->addSysOperLog($operLogParam);
        return $response;
    }

    // 处理方法注解
    private function processAnnoationParam(string $controllerName, string $actionName, array &$operLogParam)
    {
        $controller = new \ReflectionClass($controllerName);
        $document = $controller->getMethod($actionName)->getDocComment();
        preg_match_all('/@(\w+)\s+([^\s*]+)/', $document, $values);
        $operLogParam['title'] = $values[2][0];
        $operLogParam['oper_type'] = $this->getDynamicBussinessType($values[2][1]);
    }

    private function getDynamicBussinessType($type)
    {
        $businessType = new \ReflectionClass(BusinessType::class);
        $constants = $businessType->getConstants();
        return $constants[$type];
    }
}